Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix($parse): standardize one-time literal vs non-literal and interceptors #15858

Merged
merged 3 commits into from
Mar 31, 2017

Conversation

jbedard
Copy link
Collaborator

@jbedard jbedard commented Mar 24, 2017

Previously literal one-time bindings did not use the expression inputs, causing infinite digest issues with literal values. This often forces the use of deepEquals when watching one-time literals.

ng-class is one example of deepEquals which is no longer required (and had to be updated to keep all tests passing).

This one-time/literal behavior is now also consistently propagated through interceptors (and had to be updated to keep all tests passing).


The ngClass/interceptor part was not originally planned but had to be changed to keep tests passing. Maybe this can be split into smaller commits? But it's mainly just deleting...!

@@ -97,15 +90,9 @@ function classDirective(name, selector) {
oldModulo = newModulo;
}

function ngClassOneTimeWatchAction(newClassValue) {
function ngClassWatchAction(newClassValue) {
var newClassString = toClassString(newClassValue);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since toClassString is being used as an interceptor, is it necessary to pass it through toClassString again here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're correct, updated...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we were wrong. In the case of one-time bindings the pre-interceptor value is returned up until that value passes the one-time test:

return isDefined(value) ? result : value;

I've updated it to do this toClassString conditionally and added a comment.

}
function isAllDefined(value) {
var allDefined = true;
forEach(value, function(val) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Not directly related to this PR, but I think it makes sense to exit early once an undefined value is found.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think value can be an object or array which forEach currently handles or us. Did you have something in mind?

Since this is currently only used for object/array literal cases, we could split this into separate object/array helper methods (one using for-in one using array.every?)...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it is not worth it. It is just for one-time literals and it will only matter if one has huge literals which don't settle quickly (a very unlikely usecase).

@jbedard jbedard force-pushed the one-time-literal branch 2 times, most recently from 775281c to 1ef435b Compare March 29, 2017 07:29
…tors

Previously literal one-time bindings did not use the expression `inputs`, causing infinite digest issues with literal values. This often forces the use of deepEquals when watching one-time literals.

`ng-class` is one example of deepEquals which is no longer required.

This one-time/literal behavior is now also consistently propogated through interceptors.
if (newClassString !== oldClassString) {
ngClassWatchAction(newClassString);
function ngClassWatchAction(newClassString) {
//When using a one-time binding the newClassString will return
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You realy don't like spaces after //, do you 😛

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bad (or just different!) habit I guess :)

function ngClassWatchAction(newClassString) {
//When using a one-time binding the newClassString will return
//the pre-interceptor value until the one-time is complete
if (newClassString && typeof newClassString !== "string") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just !isString(newClassString)?
Also, I don't think it makes much difference over always applying toClassString() (which just does isArray() and isObject()).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated to isString. I kind of like an if block just so it's obvious that the comment applies to the full block, nothing more nothing less...

src/ng/parse.js Outdated
@@ -1859,6 +1859,7 @@ function $ParseProvider() {
}

function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {
var doneCriteria = parsedExpression.literal ? isAllDefined : isDefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could have a better name, e.g. isDone, fulfillsDoneCriteria, because it's not very descriptive when called later on

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, done.

@jbedard
Copy link
Collaborator Author

jbedard commented Mar 31, 2017

I think this is ready, PTAL.

@googlebot
Copy link

So there's good news and bad news.

👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there.

😕 The bad news is that it appears that one or more commits were authored by someone other than the pull request submitter. We need to confirm that they're okay with their commits being contributed to this project. Please have them confirm that here in the pull request.

Note to project maintainer: This is a terminal state, meaning the cla/google commit status will not change from this state. It's up to you to confirm consent of the commit author(s) and merge this pull request when appropriate.

1 similar comment
@googlebot
Copy link

So there's good news and bad news.

👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there.

😕 The bad news is that it appears that one or more commits were authored by someone other than the pull request submitter. We need to confirm that they're okay with their commits being contributed to this project. Please have them confirm that here in the pull request.

Note to project maintainer: This is a terminal state, meaning the cla/google commit status will not change from this state. It's up to you to confirm consent of the commit author(s) and merge this pull request when appropriate.

@Narretz Narretz merged commit 189461f into angular:master Mar 31, 2017
Narretz pushed a commit that referenced this pull request Mar 31, 2017
…tors

Previously literal one-time bindings did not use the expression `inputs`, causing infinite digest issues with literal values. This often forces the use of deepEquals when watching one-time literals.

`ng-class` is one example of deepEquals which is no longer required.

This one-time/literal behavior is now also consistently propogated through interceptors.

Closes #15858
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants